#include "telco.h"

//Constructores
TelCO::TelCO(){
    Lista<Usuario> us;
    Lista<Gateway> gs;
    init (us,gs);
}

TelCO::TelCO(Lista<Usuario>& u, Lista<Gateway>& g){
    Lista<pair<SMS,SMS> > ls;
    init (u,g);
}

void TelCO::init (Lista<Usuario>& u, Lista<Gateway>& g){
    _mensajes = Lista<pair<SMS,SMS> >();
    _usuarios = u;
    _gateways = g;
}

//Getters
Lista<Usuario> TelCO::usuarios() const{
    return _usuarios;
}

Lista<pair<SMS,SMS> > TelCO::mensajes() const{
    return _mensajes;
}

Lista<Gateway> TelCO::gateways() const{
    return _gateways;
}

//procesarMensaje
void TelCO::procesarMensaje(const Usuario u, const SMS& s){
    Gateway g = dameGateway(s.nroDestino());
    SMS rta;
    Texto comando = primerPalabra(s.texto());
    pair <SMS, SMS> tuplaRta;
    //Saco el Gateway para modificarlo
    _gateways.sacar(g);
    //Me fijo si es comando
    if (g.comandos().pertenece(comando))
        rta = g.procesarComando(u, s);
    else //No es comando
        rta = g.procesarMensaje(u, s);
    //Agrego el Gateway modificado
    _gateways.agregar(g);
    //Asigno la tupla resultante
    tuplaRta.first = s;
    tuplaRta.second = rta;
    //Agrego la tupla al telco
    _mensajes.agregarAtras(tuplaRta);
}

Gateway TelCO::dameGateway(Numero n) const{
    int i = 0;
    Gateway res, g;
    while (i < gateways().longitud()){
        g = gateways().iesimo(i);
        if (g.numero() == n)
            res = g;
        i++;
    }
    if (res.numero() != n)
        cerr << "Gateway inexistente {dameGateway}";
    return res;
}
//Fin procesarMensaje

//infoGateways
Lista< pair<Gateway, pair< int,int > > > TelCO:: infoGateways() const{
    Lista< pair<Gateway, pair< int,int > > > lista;
    pair<Gateway, pair< int,int > > dupla;
    int i=0, cantTrivias=0, cantUsuarios=0;
    while (i < gateways().longitud()){
        Gateway g = gateways().iesimo(i);
        cantTrivias = g.trivias().longitud();
        cantUsuarios = usuariosDeLasTrivias (g);
        dupla.first = g;
        dupla.second = pair <int,int> (cantTrivias,cantUsuarios);
        lista.agregar(dupla);
        i++;
    }
    return lista;
}

int TelCO:: usuariosDeLasTrivias(const Gateway& g) const{
    int i=0;
    int acum=0;
    Lista<Trivia> trivias = g.trivias();
    while (i < usuarios().longitud()){
        if( estaEnAlgunaTrivia(usuarios().iesimo(i), trivias) )
            acum++;
        i++;
    }
    return acum;
}

bool TelCO:: estaEnAlgunaTrivia(const Usuario u, const Lista<Trivia>& trivias) const{
    Lista <Usuario> us;
    int i=0;
    while (i < trivias.longitud()){
        us.concatenar(trivias.iesimo(i).participantes());
        i++;
    }
    return us.pertenece(u);
}
//Fin infoGateways

//Operadores
bool TelCO::operator==(const TelCO& t) const{
    return mensajes() == t.mensajes()
           && usuarios() == t.usuarios()
           && gateways() == t.gateways();
}

void TelCO::mostrar(std::ostream& os) const{
    int i = 0;
    SMS original, rta;
    os << "Lista de usuarios: " << endl;
    while (i < usuarios().longitud()){
        os << "-- Usuario numero " << i << ": " << usuarios().iesimo(i) << endl;
        i++;
    }
    i = 0;
    os << "Lista de Gateways: " << endl;
    while (i < gateways().longitud()){
        os << "-- Gateway numero " << i << ": " << endl;
        gateways().iesimo(i).mostrar(os);
        os << endl;
        i++;
    }
    i = 0;
    os << "Lista de mensajes: " << endl;
    while (i < mensajes().longitud()){
        original = mensajes().iesimo(i).first;
        rta = mensajes().iesimo(i).second;
        os << "-- Mensaje numero " << i << ": " << endl;
        os << "---- Original: ";
        os << endl;
        original.mostrar(os);
        os << endl;
        os << "---- Respuesta: ";
        os << endl;
        rta.mostrar(os);
        os << endl;
        i++;
    }
}

void TelCO::guardar(std::ostream& os) const{

    int i = 0;
    SMS original, rta;
    //Identificador
    os << "T ";

    //Lista de usuarios
    os << usuarios() << " ";

    //Lista de gateways
    os << "[";
    while (i < gateways().longitud()){
        if(i != 0) os << ",";
        gateways().iesimo(i).guardar(os);
        i++;
    }
    os << "] ";

    //Lista de mensajes
    i = 0;
    os << "[";
    while (i < mensajes().longitud()){
        if(i != 0) os << ",";
        original = mensajes().iesimo(i).first;
        rta = mensajes().iesimo(i).second;
        //Dupla
        os << "(";
        original.guardar(os);
        os << ", ";
        rta.guardar(os);
        os << ")";
        i++;
    }
    os << "]";

}


void TelCO::cargar (std::istream& is){
    //Variables finales
    Lista<Usuario> usuarios;
    Lista<Gateway> gateways;
    Lista< pair<SMS,SMS> > mensajes;

    //Variables temporales
    char c;
    Usuario usuario;
    Gateway gateway;
    pair<SMS,SMS> duplaSMS;
    SMS sms;

    is >> c; //Encabezado

    //Si le encabezado es correcto
    if(c == ENCABEZADO_ARCHIVO)
    {
        //Cargamos lista de usuarios
        is >> c;//[
        while(c != ']')
        {
            is >> usuario;
            usuarios.agregarAtras(usuario);
            is >> c;
        }

        //Cargamos lista de gateways
        is >> c;//[
        while(c != ']')
        {
            gateway.cargar(is);
            gateways.agregarAtras(gateway);
            is >> c;
        }

        //Cargamos lista de duplas de sms
        is >> c;//[
        while(c != ']' && is.peek() != ']')
        {
            is >> c; //(
            sms.cargar(is);
            duplaSMS.first = sms;

            is >> c; //,
            sms.cargar(is);
            duplaSMS.second = sms;

            mensajes.agregarAtras(duplaSMS);

            is >> c; //)
            is >> c; // , o ]
        }

        //Asignamos los atributos con las finales
        _usuarios = usuarios;
        _gateways = gateways;
        _mensajes = mensajes;
    }

}
